﻿using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
using CTS.App.Com.Domain.Controller;
using CTS.Com.Domain.Enum;
using CTS.Com.Domain.Exceptions;
using CTS.Com.Domain.Helper;
using CTS.Com.Domain.Logic;
using CTS.Com.Domain.Model;
using DevExpress.Xpf.Core;
using DevExpress.Xpf.Ribbon;

namespace CTS.App.Com.Domain.Helper
{
    public static class FormHelper
    {
        public static void Focus(this UIElement el)
        {
            Action a = () => el.Focus();
            el.Dispatcher.BeginInvoke(DispatcherPriority.Background, a);
        }

        public static T GetVisualChild<T>(Visual parent) where T : Visual
        {
            T child = default(T);
            int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < numVisuals; i++) {
                var v = (Visual)VisualTreeHelper.GetChild(parent, i);
                child = v as T;
                if (child == null) {
                    child = GetVisualChild<T>(v);
                }
                if (child != null) {
                    break;
                }
            }
            return child;
        }

        public static T Invoke<T>(IOperateLogic<T> logic, object obj) where T : BasicResponse, new()
        {
            // Local variable declaration
            T viewModel = new T() { ResultFlag = false };
            try {
                // Validate
                ValidateHelper.Validate(obj);

                // Invoke processing
                viewModel = (T)logic.Invoke(obj);

                // Set message
                if (viewModel.HasMessage) {
                    SetMessage(viewModel.MessageSingle);
                }

                viewModel.ResultFlag = true;
            } catch (SysIgnoreException) {
                viewModel.ResultFlag = true;
                return viewModel;
            } catch (SysRuntimeException ex) {
                // Set message
                SetMessage(ex.Message);
                return viewModel;
            } catch (Exception ex) {
                // Set message
                DXMessageBox.Show(ex.Message, NameHelper.GetNameString("P_CM_00004"), MessageBoxButton.OK, MessageBoxImage.Error);
                return viewModel;
            }

            // Return value
            return viewModel;
        }

        public static T Invoke<T>(IOperateLogic<T> logic, object param, Type paramType) where T : BasicResponse, new()
        {
            // Local variable declaration
            T viewModel = new T() { ResultFlag = false };
            try {
                // Validate
                var obj = DataHelper.CreateObject(paramType);
                DataHelper.CopyObject(param, obj);
                ValidateHelper.Validate(obj);

                // Invoke processing
                viewModel = (T)logic.Invoke(param);

                // Set message
                if (viewModel.HasMessage) {
                    SetMessage(viewModel.MessageSingle);
                }

                viewModel.ResultFlag = true;
            } catch (SysIgnoreException) {
                viewModel.ResultFlag = true;
                return viewModel;
            } catch (SysRuntimeException ex) {
                // Set message
                SetMessage(ex.Message);
                return viewModel;
            } catch (Exception ex) {
                // Set message
                DXMessageBox.Show(ex.Message, NameHelper.GetNameString("P_CM_00004"), MessageBoxButton.OK, MessageBoxImage.Error);
                return viewModel;
            }

            // Return value
            return viewModel;
        }

        public static void SetMessage(Message msg)
        {
            switch (msg.MessageType) {
                case MessageType.Fatal:
                    DXMessageBox.Show(msg.MessageDetail, NameHelper.GetNameString("P_CM_00004"), MessageBoxButton.OK, MessageBoxImage.Error);
                    break;
                case MessageType.Error:
                    DXMessageBox.Show(msg.MessageDetail, NameHelper.GetNameString("P_CM_00005"), MessageBoxButton.OK, MessageBoxImage.Error);
                    break;
                case MessageType.Warn:
                    DXMessageBox.Show(msg.MessageDetail, NameHelper.GetNameString("P_CM_00006"), MessageBoxButton.OK, MessageBoxImage.Warning);
                    break;
                default:
                    DXMessageBox.Show(msg.MessageDetail, NameHelper.GetNameString("P_CM_00007"), MessageBoxButton.OK, MessageBoxImage.Information);
                    break;
            }
        }

        public static void OpenWindow(Type type, object param, bool isDialog)
        {
            if (type == null) return;
            if (type.BaseType != typeof(WindowBase)) return;
            var window = (WindowBase)DataHelper.CreateObject(type, param);
            if (isDialog) window.ShowDialog();
            else window.Show();
        }

        public static void OpenMainWindow(Type type, object param)
        {
            if (type == null) return;
            if (type.BaseType != typeof(DXRibbonWindow)) return;
            var window = (DXRibbonWindow)DataHelper.CreateObject(type, param);
            window.Show();
        }
    }
}
